package com.summo.demo.filter;

import java.io.IOException;
import java.util.Objects;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSONObject;

import com.summo.demo.config.redis.RedisUtil;
import com.summo.demo.config.context.GlobalUserContext;
import com.summo.demo.config.context.UserContext;
import com.summo.demo.entity.UserDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

@Slf4j
@Component
public class WebFilter implements Filter {

    private final AntPathMatcher jwtPathMatcher = new AntPathMatcher();

    @Value("${anonUrl}")
    private String anonUrl;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws ServletException, IOException {
        try {
            //获取本次接口的唯一码
            String requestId = java.util.UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
            MDC.put("requestId", requestId);
            //获取请求头
            HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
            HttpServletResponse httpServletResponse = (HttpServletResponse)servletResponse;
            log.info("当前请求链接为:[{}]", httpServletRequest.getRequestURL());
            //放过不需要校验token的接口，如login
            String requestURI = httpServletRequest.getRequestURI();
            String[] anonUrlList = StringUtils.splitByWholeSeparatorPreserveAllTokens(anonUrl,
                ",");
            boolean match = false;
            for (String u : anonUrlList) {
                if (jwtPathMatcher.match(u, requestURI)) {
                    match = true;
                    break;
                }
            }
            if (match) {
                log.info("当前接口不需要进行token认证,requestURI={}", requestURI);
                filterChain.doFilter(httpServletRequest, httpServletResponse);
                return;
            }
            //从Cookie中获取token
            String token = null;
            for (Cookie cookie : httpServletRequest.getCookies()) {
                if (StringUtils.equals("token", cookie.getName())) {
                    token = cookie.getValue();
                }
            }
            if (StringUtils.isEmpty(token)) {
                throw new RuntimeException("当前用户身份已失效");
            }
            //从缓存中查询用户信息
            Object temp = redisUtil.get(token);
            if (Objects.isNull(temp)) {
                throw new RuntimeException("当前用户身份已失效");
            }
            UserDO userDO = JSONObject.parseObject((String)temp, UserDO.class);
            //设置用户上下文
            UserContext userContext = new UserContext();
            userContext.setUserId(userDO.getUserId());
            GlobalUserContext.setUserContext(userContext);
            //执行doFilter，这行一定要加，否则程序会中断掉
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } catch (Exception e) {
            log.error("do doFilter exception", e);
            throw e;
        } finally {
            GlobalUserContext.clear();
            MDC.remove("requestId");
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
